using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Stimik
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        ContentManager content;

        // Set the position of the model in world space, and set the rotation.
        Vector3 modelPosition = new Vector3(0.0f, 0.0f, 0.0f);

        float[,] modelRotationX = new float[RUBIK_SIZE,4] { {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f},
                                                            {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f},
                                                            {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f} };
        float[,] modelRotationY = new float[RUBIK_SIZE,4] { {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f},
                                                            {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f},
                                                            {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f} };
        float[,] modelRotationZ = new float[RUBIK_SIZE,4] { {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f},
                                                            {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f},
                                                            {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f} };

        // Set the position of the camera in world space, for our view matrix.
        Vector3 cameraPosition = new Vector3(-7.5f, 7.5f, 10.0f);
        Matrix projectionMatrix;
        Matrix viewMatrix;

        // Set the 3D model to draw.
        Model[,] myModel = new Model[RUBIK_SIZE, 4];

        // The aspect ratio determines how to scale 3d to 2d projection.
        float aspectRatio;

        // Solver speed
        float solverSpeed = NORMAL;
        const float SLOW = 0.1f;
        const float NORMAL = 0.5f;
        const float FAST = 1.0f;

        // Rubik size
        const int RUBIK_SIZE = 8;

        // boolean
        //bool isRotateX = false;
        //bool isRotateY = false;
        //bool isRotateZ = false;
        bool isSolverRotating = false;
        bool isRotating = false;
        bool isKeyPressed = false;
        bool right = false;
        bool rightCC = false;
        bool face = false;
        bool faceCC = false;
        bool up = false;
        bool upCC = false;

        //rubik solver
        RubikSolver rs;
        Rubiks startRubiks;
        List<int> pathToSolution;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            content = new ContentManager(Services);
            aspectRatio = (float)GraphicsDeviceManager.DefaultBackBufferWidth /
                (float)GraphicsDeviceManager.DefaultBackBufferHeight;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            //Rubiks r = new Rubiks(2, new char[,] { { '6', '1' }, { '1', '3' } }, new char[,] { { '3', '6' }, { '6', '1' } }, new char[,] { { '1', '3' }, { '2', '6' } }, new char[,] { { '4', '5' }, { '5', '5' } }, new char[,] { { '5', '2' }, { '2', '2' } }, new char[,] { { '3', '4' }, { '4', '4' } });
            //r.testprint();
            rs = new RubikSolver(@"MyFile.txt");
            rs.solve();
            startRubiks = rs.getStartRubiks;
            pathToSolution = rs.getSolPath;
            Rubiks r = new Rubiks(2, new char[,] { { '1', '1' }, { '1', '1' } }, new char[,] { { '2', '2' }, { '2', '2' } }, new char[,] { { '3', '3' }, { '3', '3' } }, new char[,] { { '4', '4' }, { '4', '4' } }, new char[,] { { '5', '5' }, { '5', '5' } }, new char[,] { { '6', '6' }, { '6', '6' } });
            List<int> l = new List<int>();
            l.Add(6);
            l.Add(6);
            l.Add(6);
            r.testprint();
            Rubiks test = Rubiks.createRubiksFromOpr(r,l);
            test.testprint();

            projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 200.0f);
            viewMatrix = Matrix.CreateLookAt(cameraPosition, Vector3.Zero, Vector3.Up);

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        SpriteBatch foregroundBatch;
        SpriteFont spriteFont;
        Vector2 authorPos;
        Vector2 helpPos;
        float fontRotation;

        protected override void LoadContent()
        {
            // TODO: use this.Content to load your game content here.
            myModel[0, 0] = content.Load<Model>(@"Content\Models\Cube0");
            myModel[0, 1] = content.Load<Model>(@"Content\Models\Face0");
            myModel[0, 2] = content.Load<Model>(@"Content\Models\Face1");
            myModel[0, 3] = content.Load<Model>(@"Content\Models\Face2");
            myModel[1, 0] = content.Load<Model>(@"Content\Models\Cube1");
            myModel[1, 1] = content.Load<Model>(@"Content\Models\Face3");
            myModel[1, 2] = content.Load<Model>(@"Content\Models\Face4");
            myModel[1, 3] = content.Load<Model>(@"Content\Models\Face5");
            myModel[2, 0] = content.Load<Model>(@"Content\Models\Cube2");
            myModel[2, 1] = content.Load<Model>(@"Content\Models\Face6");
            myModel[2, 2] = content.Load<Model>(@"Content\Models\Face7");
            myModel[2, 3] = content.Load<Model>(@"Content\Models\Face8");
            myModel[3, 0] = content.Load<Model>(@"Content\Models\Cube3");
            myModel[3, 1] = content.Load<Model>(@"Content\Models\Face9");
            myModel[3, 2] = content.Load<Model>(@"Content\Models\Face10");
            myModel[3, 3] = content.Load<Model>(@"Content\Models\Face11");
            myModel[4, 0] = content.Load<Model>(@"Content\Models\Cube4");
            myModel[4, 1] = content.Load<Model>(@"Content\Models\Face12");
            myModel[4, 2] = content.Load<Model>(@"Content\Models\Face13");
            myModel[4, 3] = content.Load<Model>(@"Content\Models\Face14");
            myModel[5, 0] = content.Load<Model>(@"Content\Models\Cube5");
            myModel[5, 1] = content.Load<Model>(@"Content\Models\Face15");
            myModel[5, 2] = content.Load<Model>(@"Content\Models\Face16");
            myModel[5, 3] = content.Load<Model>(@"Content\Models\Face17");
            myModel[6, 0] = content.Load<Model>(@"Content\Models\Cube6");
            myModel[6, 1] = content.Load<Model>(@"Content\Models\Face18");
            myModel[6, 2] = content.Load<Model>(@"Content\Models\Face19");
            myModel[6, 3] = content.Load<Model>(@"Content\Models\Face20");
            myModel[7, 0] = content.Load<Model>(@"Content\Models\Cube7");
            myModel[7, 1] = content.Load<Model>(@"Content\Models\Face21");
            myModel[7, 2] = content.Load<Model>(@"Content\Models\Face22");
            myModel[7, 3] = content.Load<Model>(@"Content\Models\Face23");

            spriteFont = content.Load<SpriteFont>(@"Content\SpriteFont1");
            foregroundBatch = new SpriteBatch(graphics.GraphicsDevice);
            //fontPos = new Vector2(graphics.GraphicsDevice.Viewport.Width/2, graphics.GraphicsDevice.Viewport.Height-15);
            authorPos = new Vector2(0.0f + 120, 0.0f + 40);
            helpPos = new Vector2(graphics.GraphicsDevice.Viewport.Width / 2 + 250, 0.0f + 65);
            fontRotation = 0;
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
            content.Unload();
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here
            updateInput(gameTime);

            if (isSolverRotating == true)
            {
                if ((isRotating == false) && (isKeyPressed == false))
                {
                    if (pathToSolution.Count == 0)
                    {
                        isSolverRotating = false;
                    }

                    executeSolver();
                }

                if (right == true)
                {
                    opRightExecution(gameTime);

                    if (modelRotationX[1, 0] >= 0)
                    {
                        if ((modelRotationX[1, 0] % 1.57f) <= 0.05f)
                        {
                            isRotating = false;
                            right = false;

                            if (isKeyPressed == true)
                            {
                                isSolverRotating = false;
                                isKeyPressed = false;
                            }
                        }
                    }
                    else
                    {
                        if ((modelRotationX[1, 0] % -1.57f) >= -0.04f)
                        {
                            isRotating = false;
                            right = false;

                            if (isKeyPressed == true)
                            {
                                isSolverRotating = false;
                                isKeyPressed = false;
                            }
                        }
                    }
                }
                else if (rightCC == true)
                {
                    opRightCCExecution(gameTime);

                    if (modelRotationX[1, 0] >= 0)
                    {
                        if ((modelRotationX[1, 0] % 1.57f) <= 0.05f)
                        {
                            isRotating = false;
                            rightCC = false;

                            if (isKeyPressed == true)
                            {
                                isSolverRotating = false;
                                isKeyPressed = false;
                            }
                        }
                    }
                    else
                    {
                        if ((modelRotationX[1, 0] % -1.57f) >= -0.04f)
                        {
                            isRotating = false;
                            rightCC = false;

                            if (isKeyPressed == true)
                            {
                                isSolverRotating = false;
                                isKeyPressed = false;
                            }
                        }
                    }
                }
                else if (face == true)
                {
                    opFaceExecution(gameTime);

                    if (modelRotationZ[2, 0] >= 0)
                    {
                        if ((modelRotationZ[2, 0] % 1.57f) <= 0.05f)
                        {
                            isRotating = false;
                            face = false;

                            if (isKeyPressed == true)
                            {
                                isSolverRotating = false;
                                isKeyPressed = false;
                            }
                        }
                    }
                    else
                    {
                        if ((modelRotationZ[2, 0] % -1.57f) >= -0.04f)
                        {
                            isRotating = false;
                            face = false;

                            if (isKeyPressed == true)
                            {
                                isSolverRotating = false;
                                isKeyPressed = false;
                            }
                        }
                    }
                }
                else if (faceCC == true)
                {
                    opFaceCCExecution(gameTime);
                    System.Diagnostics.Debug.WriteLine(modelRotationZ[2, 0] % 1.57f);

                    if (modelRotationZ[2, 0] >= 0)
                    {
                        if ((modelRotationZ[2, 0] % 1.57f) <= 0.05f)
                        {
                            isRotating = false;
                            faceCC = false;

                            if (isKeyPressed == true)
                            {
                                isSolverRotating = false;
                                isKeyPressed = false;
                            }
                        }
                    }
                    else
                    {
                        if ((modelRotationZ[2, 0] % -1.57f) >= -0.04f)
                        {
                            isRotating = false;
                            faceCC = false;

                            if (isKeyPressed == true)
                            {
                                isSolverRotating = false;
                                isKeyPressed = false;
                            }
                        }
                    }
                }
                else if (up == true)
                {
                    opUpExecution(gameTime);

                    if (modelRotationY[0, 0] >= 0)
                    {
                        if ((modelRotationY[0, 0] % 1.57f) <= 0.05f)
                        {
                            isRotating = false;
                            up = false;

                            if (isKeyPressed == true)
                            {
                                isSolverRotating = false;
                                isKeyPressed = false;
                            }
                        }
                    }
                    else
                    {
                        if ((modelRotationY[0, 0] % -1.57f) >= -0.04f)
                        {
                            isRotating = false;
                            up = false;

                            if (isKeyPressed == true)
                            {
                                isSolverRotating = false;
                                isKeyPressed = false;
                            }
                        }
                    }
                }
                else if (upCC == true)
                {
                    opUpCCExecution(gameTime);

                    if (modelRotationY[0, 0] >= 0)
                    {
                        if ((modelRotationY[0, 0] % 1.57f) <= 0.05f)
                        {
                            isRotating = false;
                            upCC = false;

                            if (isKeyPressed == true)
                            {
                                isSolverRotating = false;
                                isKeyPressed = false;
                            }
                        }
                    }
                    else
                    {
                        if ((modelRotationY[0, 0] % -1.57f) >= -0.04f)
                        {
                            isRotating = false;
                            upCC = false;

                            if (isKeyPressed == true)
                            {
                                isSolverRotating = false;
                                isKeyPressed = false;
                            }
                        }
                    }
                }
            }

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            // TODO: Add your drawing code here
            // Copy any parent transforms.
            for (int i = 0; i < RUBIK_SIZE * 4; i++)
            {
                Matrix[] transforms = new Matrix[myModel[i / 4, i % 4].Bones.Count];
                myModel[i / 4, i % 4].CopyAbsoluteBoneTransformsTo(transforms);

                // Draw the model. A model can have multiple meshes, so loop.
                foreach (ModelMesh mesh in myModel[i / 4, i % 4].Meshes)
                {
                    // This is where the mesh orientation is set, as well as our camera and projection.
                    foreach (BasicEffect effect in mesh.Effects)
                    {
                        effect.EnableDefaultLighting();
                        effect.World = transforms[mesh.ParentBone.Index] *
                            Matrix.CreateRotationX(modelRotationX[i / 4, i % 4]) *
                            Matrix.CreateRotationY(modelRotationY[i / 4, i % 4]) *
                            Matrix.CreateRotationZ(modelRotationZ[i / 4, i % 4]) *
                            Matrix.CreateTranslation(modelPosition);
                        effect.View = this.viewMatrix;
                        effect.Projection = this.projectionMatrix;

                        if (i % 4 != 0) // Set rubick colour
                        {
                            if ((i % 4 == 1) && ((i / 4 == 0) || (i / 4 == 2) || (i / 4 == 4) || (i / 4 == 6))) //left
                            {
                                if (i / 4 == 0)
                                {
                                    setColour(effect, startRubiks.Left[0, 0]);
                                }
                                else if (i / 4 == 2)
                                {
                                    setColour(effect, startRubiks.Left[0, 1]);
                                }
                                else if (i / 4 == 4)
                                {
                                    setColour(effect, startRubiks.Left[1, 0]);
                                }
                                else if (i / 4 == 6)
                                {
                                    setColour(effect, startRubiks.Left[1, 1]);
                                }
                            }
                            else if ((i % 4 == 1) && ((i / 4 == 1) || (i / 4 == 3) || (i / 4 == 5) || (i / 4 == 7))) //right
                            {
                                if (i / 4 == 1)
                                {
                                    setColour(effect, startRubiks.Right[0, 1]);
                                }
                                else if (i / 4 == 3)
                                {
                                    setColour(effect, startRubiks.Right[0, 0]);
                                }
                                else if (i / 4 == 5)
                                {
                                    setColour(effect, startRubiks.Right[1, 1]);
                                }
                                else if (i / 4 == 7)
                                {
                                    setColour(effect, startRubiks.Right[1, 0]);
                                }
                            }
                            else if ((i % 4 == 2) && ((i / 4 == 0) || (i / 4 == 1) || (i / 4 == 4) || (i / 4 == 5))) //back
                            {
                                if (i / 4 == 0)
                                {
                                    setColour(effect, startRubiks.Back[0, 0]);
                                }
                                else if (i / 4 == 1)
                                {
                                    setColour(effect, startRubiks.Back[0, 1]);
                                }
                                else if (i / 4 == 4)
                                {
                                    setColour(effect, startRubiks.Back[1, 0]);
                                }
                                else if (i / 4 == 5)
                                {
                                    setColour(effect, startRubiks.Back[1, 1]);
                                }
                            }
                            else if ((i % 4 == 2) && ((i / 4 == 2) || (i / 4 == 3) || (i / 4 == 6) || (i / 4 == 7))) //face
                            {
                                if (i / 4 == 2)
                                {
                                    setColour(effect, startRubiks.Face[0, 0]);
                                }
                                else if (i / 4 == 3)
                                {
                                    setColour(effect, startRubiks.Face[0, 1]);
                                }
                                else if (i / 4 == 6)
                                {
                                    setColour(effect, startRubiks.Face[1, 0]);
                                }
                                else if (i / 4 == 7)
                                {
                                    setColour(effect, startRubiks.Face[1, 1]);
                                }
                            }
                            else if ((i % 4 == 3) && ((i / 4 == 0) || (i / 4 == 1) || (i / 4 == 2) || (i / 4 == 3))) //up
                            {
                                if (i / 4 == 0)
                                {
                                    setColour(effect, startRubiks.Up[0, 0]);
                                }
                                else if (i / 4 == 1)
                                {
                                    setColour(effect, startRubiks.Up[0, 1]);
                                }
                                else if (i / 4 == 2)
                                {
                                    setColour(effect, startRubiks.Up[1, 0]);
                                }
                                else if (i / 4 == 3)
                                {
                                    setColour(effect, startRubiks.Up[1, 1]);
                                }
                            }
                            else if ((i % 4 == 3) && ((i / 4 == 4) || (i / 4 == 5) || (i / 4 == 6) || (i / 4 == 7))) //down
                            {
                                if (i / 4 == 4)
                                {
                                    setColour(effect, startRubiks.Down[1, 0]);
                                }
                                else if (i / 4 == 5)
                                {
                                    setColour(effect, startRubiks.Down[1, 1]);
                                }
                                else if (i / 4 == 6)
                                {
                                    setColour(effect, startRubiks.Down[0, 0]);
                                }
                                else if (i / 4 == 7)
                                {
                                    setColour(effect, startRubiks.Down[0, 1]);
                                }
                            }
                        }
                    }
                    // Draw the mesh, using the effects set above.
                    mesh.Draw();
                }
            }

            foregroundBatch.Begin();

            string author = "Author :\n" +
                            "Muhammad Hilman Beyri\n" +
                            "Prisyafandiafif Charifa\n" +
                            "Sahat Nicholas Simangunsong";

            string help = "Help :\n" +
                          "Enter --> Solve the rubick\n" +
                          "Left arrow --> Game speed : slow\n" +
                          "Up Arrow --> Game speed : normal\n" +
                          "Right Arrow --> Game speed : fast\n";

            // Find the center of the string
            Vector2 authorOrigin = spriteFont.MeasureString(author) / 2;
            // Draw the string
            foregroundBatch.DrawString(spriteFont, author, authorPos, Color.LightGreen, fontRotation, authorOrigin, 1.0f, SpriteEffects.None, 0.5f);

            // Find the center of the string
            Vector2 helpOrigin = spriteFont.MeasureString(help) / 2;
            // Draw the string
            foregroundBatch.DrawString(spriteFont, help, helpPos, Color.LightGreen, fontRotation, helpOrigin, 1.0f, SpriteEffects.None, 0.5f);

            foregroundBatch.End();

            base.Draw(gameTime);
        }

        private void setColour(BasicEffect effect, char cubeSide)
        {
            if (cubeSide.Equals('1'))
            {
                effect.DiffuseColor = new Vector3(2.0f, 2.0f, 2.0f); //white
            }
            else if (cubeSide.Equals('2'))
            {
                effect.DiffuseColor = new Vector3(0.0f, 0.0f, 1.0f); //blue    
            }
            else if (cubeSide.Equals('3'))
            {
                effect.DiffuseColor = new Vector3(1.0f, 0.0f, 0.0f); //red
            }
            else if (cubeSide.Equals('4'))
            {
                effect.DiffuseColor = new Vector3(0.0f, 1.0f, 0.0f); //green
            }
            else if (cubeSide.Equals('5'))
            {
                effect.DiffuseColor = new Vector3(1.0f, 0.0f, 1.0f); //purple
            }
            else
            {
                effect.DiffuseColor = new Vector3(2.0f, 2.0f, 0.0f); //yellow
            }
        }

        private void updateInput(GameTime gameTime)
        {
            KeyboardState userInput = Keyboard.GetState();

            if (userInput.IsKeyDown(Keys.Left))
            {
                solverSpeed = SLOW;
            }
            else if (userInput.IsKeyDown(Keys.Up))
            {
                solverSpeed = NORMAL;
            }
            else if (userInput.IsKeyDown(Keys.Right))
            {
                solverSpeed = FAST;
            }
            if ((userInput.IsKeyDown(Keys.Q)) && (isSolverRotating == false))
            {
                isSolverRotating = true;
                isKeyPressed = true;
                right = true;
            }
            if ((userInput.IsKeyDown(Keys.W)) && (isSolverRotating == false))
            {
                isSolverRotating = true;
                isKeyPressed = true;
                rightCC = true;
            }
            if ((userInput.IsKeyDown(Keys.E)) && (isSolverRotating == false))
            {
                isSolverRotating = true;
                isKeyPressed = true;
                face = true;
            }
            if ((userInput.IsKeyDown(Keys.R)) && (isSolverRotating == false))
            {
                isSolverRotating = true;
                isKeyPressed = true;
                faceCC = true;
            }
            if ((userInput.IsKeyDown(Keys.T)) && (isSolverRotating == false))
            {
                isSolverRotating = true;
                isKeyPressed = true;
                up = true;
            }
            if ((userInput.IsKeyDown(Keys.Y)) && (isSolverRotating == false))
            {
                isSolverRotating = true;
                isKeyPressed = true;
                upCC = true;
            }

            /*
            if ((userInput.IsKeyDown(Keys.A)) && (isSolverRotating == false))
            {
                isRotateX = true;
            }
            if ((userInput.IsKeyDown(Keys.S)) && (isSolverRotating == false))
            {
                isRotateY = true;
            }
            if ((userInput.IsKeyDown(Keys.D)) && (isSolverRotating == false))
            {
                isRotateZ = true;
            }
            if (userInput.IsKeyUp(Keys.A))
            {
                isRotateX = false;
            }
            if (userInput.IsKeyUp(Keys.S))
            {
                isRotateY = false;
            }
            if (userInput.IsKeyUp(Keys.D))
            {
                isRotateZ = false;
            }
            */

            if (userInput.IsKeyDown(Keys.Enter))
            {
                for (int i = 0; i < RUBIK_SIZE; i++)
                {
                    for (int j = 0; j < 4; j++)
                    {
                        modelRotationX[i, j] = 0.0f;
                        modelRotationY[i, j] = 0.0f;
                        modelRotationZ[i, j] = 0.0f;
                    }
                }

                isSolverRotating = true;
            }
        }

        private void opRightExecution(GameTime gameTime)
        {
            int j = 0;

            for (j = 0; j < 4; j++)
            {
                modelRotationX[1, j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationX[3, j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationX[5, j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationX[7, j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
            }
        }

        private void opRightCCExecution(GameTime gameTime)
        {
            for (int j = 0; j < 4; j++)
            {
                modelRotationX[1, j] -= (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationX[3, j] -= (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationX[5, j] -= (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationX[7, j] -= (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
            }
        }

        private void opFaceCCExecution(GameTime gameTime)
        {
            for (int j = 0; j < 4; j++)
            {
                modelRotationZ[2, j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationZ[3, j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationZ[6, j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationZ[7, j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
            }
        }

        private void opFaceExecution(GameTime gameTime)
        {
            for (int j = 0; j < 4; j++)
            {
                modelRotationZ[2, j] -= (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationZ[3, j] -= (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationZ[6, j] -= (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationZ[7, j] -= (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
            }
        }

        private void opUpExecution(GameTime gameTime)
        {
            for (int j = 0; j < 4; j++)
            {
                modelRotationY[0, j] -= (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationY[1, j] -= (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationY[2, j] -= (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationY[3, j] -= (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
            }
        }

        private void opUpCCExecution(GameTime gameTime)
        {
            for (int j = 0; j < 4; j++)
            {
                modelRotationY[0, j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationY[1, j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationY[2, j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
                modelRotationY[3, j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f) * solverSpeed;
            }
        }

        /*
        private void rotateCube(GameTime gameTime)
        {
            for (int i = 0; i < RUBIK_SIZE; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    if (isRotateX == true)
                    {
                        modelRotationX[i,j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f);
                    }
                    if (isRotateY == true)
                    {
                        modelRotationY[i,j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f);
                    }
                    if (isRotateZ == true)
                    {
                        modelRotationZ[i,j] += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.1f);
                    }
                }
            }
        }
        */

        private void executeSolver()
        {
            if (pathToSolution.Count != 0)
            {
                isRotating = true;

                if (pathToSolution[0] == 0)
                {
                    isRotating = false;
                }
                else if (pathToSolution[0] == Rubiks.RIGHTC)
                {
                    right = true;
                }
                else if (pathToSolution[0] == Rubiks.RIGHTCC)
                {
                    rightCC = true;
                }
                else if (pathToSolution[0] == Rubiks.FACEC)
                {
                    face = true;
                }
                else if (pathToSolution[0] == Rubiks.FACECC)
                {
                    faceCC = true;
                }
                else if (pathToSolution[0] == Rubiks.UPC)
                {
                    up = true;
                }
                else if (pathToSolution[0] == Rubiks.UPCC)
                {
                    upCC = true;
                }

                pathToSolution.RemoveAt(0);
            }
        }
    }
}
